/**
 * Copyright (C) 2013 AirChina
 *
 * @description:
 * @version:v1.0.0
 */
package com.china.itapi.common.util;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.net.ssl.SSLContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.HttpContext;

import com.google.gson.Gson;


/**
 * @Description:
 * @author:larry
 * @Created:2013-10-22下午12:09:58
 */
public class HttpUtil {


	private static Log log = LogFactory.getLog(HttpUtil.class);
	private static DefaultHttpClient httpClient;

	private static int maxConLifeTimeMs = 300000;
	private static int defaultMaxConPerHost = 50;
	private static int maxTotalConn = 10000;
	private static int conTimeOutMs = 10000;
	private static int soTimeOutMs = 30000;
	
	private static String boundary = "----WebKitFormBoundaryJRL6erQBYcEZhWam";  

	static {
		try {
			Scheme http = new Scheme("http", 80, PlainSocketFactory.getSocketFactory());
			SSLContext sslcontext = SSLContext.getInstance("TLS");
			sslcontext.init(null, null, null);
			SSLSocketFactory sf = new SSLSocketFactory(sslcontext, SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
			Scheme https = new Scheme("https", 443, sf);
			SchemeRegistry sr = new SchemeRegistry();
			sr.register(http);
			sr.register(https);
			PoolingClientConnectionManager cm = new PoolingClientConnectionManager(sr, maxConLifeTimeMs, TimeUnit.MILLISECONDS);
			cm.setMaxTotal(maxTotalConn);
			cm.setDefaultMaxPerRoute(defaultMaxConPerHost);
			httpClient = new DefaultHttpClient(cm);
			httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, conTimeOutMs);
			httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeOutMs);
			httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES);
			httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
				public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException {
					HttpEntity entity = response.getEntity();
					Header ceheader = entity.getContentEncoding();
					if (ceheader != null && ceheader.getValue().toLowerCase().contains("gzip")) {
						response.setEntity(new GzipDecompressingEntity(response.getEntity()));
					}
				}
			});
		} catch (Exception e) {
			log.error("HttpExecutor init error", e);
		}
	}

	public static HttpResponse execute(HttpUriRequest request) throws Exception {
		HttpResponse httpResponse;
		try {
			httpResponse = httpClient.execute(request);
		} catch (Exception e) {
			throw e;
		}
		return httpResponse;
	}
	
	
	/**
	  * <p>(适用条件[可选])
	  * <p>(执行流程[可选])
	  * <p>(使用方法[可选])
	  * <p>(注意事项[可选])
	  *
	  * @Description: 模拟 http post请求
	  * @param path 请求路径
	  * @param param 请求参数
	  * @return 请求返回的值
	  * @Created:zhouzj 2013-11-25下午2:51:15
	  * @Modified:
	 */
	public static String httpPost(String path, Map<String, String> param){
		String result = null;
		try {
			/***
			 * 如果查询结果为空，则访问9qmy游戏市场，返回数据
			 */
			// 创建一个url ,并打开一个connection
			URL url = new URL(path);
			HttpURLConnection connection = (HttpURLConnection)url.openConnection();
			
			// 设置connection 
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setRequestMethod("POST");
			connection.setUseCaches(false);
			connection.setInstanceFollowRedirects(true);
			connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			
			// 连接并设置参数
			connection.connect();
			DataOutputStream out = new DataOutputStream(connection.getOutputStream());
			
			String content = "";
			String linkChar = "";
			if(null!=param){
				Set<Map.Entry<String, String>> set = param.entrySet();
				Iterator it = set.iterator();
				while(it.hasNext()){
					Map.Entry<String, String> entry = (Map.Entry<String, String>)it.next();
					content+=linkChar+entry.getKey()+"="+URLEncoder.encode(entry.getValue(), "UTF-8");
					linkChar="&";
				}
			}
			
			out.writeBytes(content);
			out.flush();
			out.close();
			
			InputStream in = connection.getInputStream();
			StringBuffer sb = new StringBuffer();

			int i=0;
			byte[] b=new byte[1024];
			while((i = in.read(b))!=-1){
				sb.append(new String(b,0, i, "utf-8"));
			}
			
			result=sb.toString();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e){
			e.printStackTrace();
		}
		
		return result;
	}
	
	/**
	  * <p>(适用条件[可选])
	  * <p>(执行流程[可选])
	  * <p>(使用方法[可选])
	  * <p>(注意事项[可选])
	  *
	  * @Description: 上传文件 
	  * @param path  请求的url路径
	  * @param param 请求参数
	  * @return
	  * @Created:zhouzj 2013-12-4上午11:25:05
	  * @Modified:
	 */
	public static String httpUploadFile(String path, Map<String, String> param){
		String result = null;
		try {
			
			/***
			 * 如果查询结果为空
			 */
			// 创建一个url ,并打开一个connection
			URL url = new URL(path);
			HttpURLConnection connection = (HttpURLConnection)url.openConnection();
			
			// 设置connection 
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setRequestMethod("POST");
			connection.setUseCaches(false);
			connection.setInstanceFollowRedirects(true);
			connection.setRequestProperty("Connection", "Keep-Alive");  
			connection.setRequestProperty("Charset", "UTF-8");  
			connection.setRequestProperty("Content-Type",  "multipart/form-data; boundary=" + boundary);  
			
			// 连接并设置参数
			connection.connect();
			DataOutputStream out = new DataOutputStream(connection.getOutputStream());
			
			String content = "";
			String linkChar = "";
			if(null!=param){
				Set<Map.Entry<String, String>> set = param.entrySet();
				Iterator it = set.iterator();
				while(it.hasNext()){
					Map.Entry<String, String> entry = (Map.Entry<String, String>)it.next();
					if(entry.getKey().endsWith(":File")){
						writeFileParams(out, entry.getKey().replace(":File", ""), new File(entry.getValue()));
					}else{
						content+=linkChar+entry.getKey()+"="+URLEncoder.encode(entry.getValue(), "UTF-8");
						linkChar="&";
					}
				}
			}
			
			out.writeBytes(content);
			out.flush();
			out.close();
			
			InputStream in = connection.getInputStream();
			StringBuffer sb = new StringBuffer();

			int i=0;
			byte[] b=new byte[1024];
			while((i = in.read(b))!=-1){
				sb.append(new String(b,0, i, "utf-8"));
			}
			
			result=sb.toString();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e){
			e.printStackTrace();
		}
		
		return result;
	}
	
	  //获取文件的上传类型，图片格式为image/png,image/jpg等。非图片为application/octet-stream  
    @SuppressWarnings("unused")
	private static String getContentType(File f) throws Exception {  
        ImageInputStream imagein = ImageIO.createImageInputStream(f);  
        if (imagein == null) {  
            return "application/octet-stream";  
        }  
        Iterator<ImageReader> it = ImageIO.getImageReaders(imagein);  
        if (!it.hasNext()) {  
            imagein.close();  
            return "application/octet-stream";  
        }  
        imagein.close();  
        return "image/" + it.next().getFormatName().toLowerCase();//将FormatName返回的值转换成小写，默认为大写  
    }  
    
    //文件数据  
    private static void writeFileParams(DataOutputStream ds, String name, File file) throws Exception {  
        File value = file;  
        ds.writeBytes("--" + boundary + "\r\n");  
        ds.writeBytes("Content-Disposition: form-data; name=\"" + name  
                + "\"; filename=\"" + URLEncoder.encode(value.getName(), "UTF-8") + "\"\r\n"); 
        ds.writeBytes("Content-Type: " + getContentType(value) + "\r\n");  
        ds.writeBytes("\r\n");  
        ds.write(getBytes(value));  
        ds.writeBytes("\r\n"+"--" + boundary + "--\r\n"); 
    }  
    
    //把文件转换成字节数组  
    private static byte[] getBytes(File f) throws Exception {  
        FileInputStream in = new FileInputStream(f);  
        ByteArrayOutputStream out = new ByteArrayOutputStream();  
        byte[] b = new byte[1024];  
        int n;  
        while ((n = in.read(b)) != -1) {  
            out.write(b, 0, n);  
        }  
        in.close();  
        return out.toByteArray();  
    }  
    
    public static void main(String[] args){
//    	Map<String, String> param = new HashMap<String, String>();
//    	param.put("media:File", "F:/2.jpg");
//    	String s = httpUploadFile("http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=zk03Nv2r-S2jWvwcyEm6bwItGqJqdvSy9rgiDczJVkVIoOZlgOXaBmh5a6VFGF8SRGYH-OfUt7wyjkEOQzZE9Y4eBELfx7E9gsJKh8diUMoRunP62xlnG6u7IUuN4ur0z7OwF5d1kx1HjH_c8lLnSw&type=image", param);
//    	System.out.println(s);
    	String path = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=8MrP3EHQuHAPRnMCaXG0p8MlN_eRM7pyOz2vOb2l0ZVG_A6-jBZT7O7fZ_zaD5rRyZngTw_DLzSDLLrgB4b8UglA3cjG011fTCWUY3AMUmeQgJmofBDEFwcnPCJl4p-gWFW-kCeZ98ujMgB8wg2yLA&type=image";
    	wechatUploadFile(path, "F:/2.jpg");
    }
    
    /**
      * <p>(适用条件[可选])
      * <p>(执行流程[可选])
      * <p>(使用方法[可选])
      * <p>(注意事项[可选])
      *
      * @Description: 上传微信图片
      * @param path 请求的微信服务器地址
      * @param filePath 文件本地的绝对路径
      * @return
      * @Created:zhouzj 2013-12-5上午10:16:34
      * @Modified:
     */
    public static Map<String, String> wechatUploadFile(String path, String filePath){
    	Map<String, String> param = new HashMap<String, String>();
    	param.put("media:File", filePath);
    	String s = httpUploadFile(path, param);
    	
    	Gson gson = new Gson();
    	Map<String, String> map = gson.fromJson(s, Map.class);
    	
    	return map;
    }
}
